Title Banner

Previous Book Contents Book Index Next

Inside Macintosh: QuickDraw GX Programmer's Overview / Part 2 - The QuickDraw GX Programming Cookbook
Chapter 5 - Using Macintosh Windows


Resizing and Zooming a Window

This programming recipe adds resizing and zooming to your windows by providing a size box and a zoom box.

The size box of a Macintosh window is drawn in the content region of the window. When you draw shapes into the window, you don't want to draw them over the size box, so you'd like to be able to set the clip property of the window view port to prevent this. However, QuickDraw GX manages
the clip property of window view ports for you; you don't have control over
this property.

To remedy this situation, you create a view port hierarchy. The simple
view port hierarchy in this recipe contains two view ports: a parent view
port and a child view port. You attach the parent view port to your window, but your shape objects reference the child view port. When you draw the shapes, QuickDraw GX still renders them in the window. However, since QuickDraw GX doesn't manage the clip property of the child view port object, you can set this property so that your shapes don't draw over the window's size box.

Figure 5-2 shows the simple window hierarchy and the clips of the parent view port and the child view port.

Figure 5-2 A window with a size box and its view hierarchy

The next recipe, "Adding Scrolling to a Window," beginning on page 169, explains how you can use this view port hierarchy to provide scrolling as well.

Overview of Recipe Steps

The steps in this recipe show you how to:

    1. Create a Macintosh window with a size box and a zoom box
    2. Create a parent view port and attach it to the window
    3. Create a child view port
    4. Set the clip of the child view port
    5. Set the child view port to be the default view port
    6. Respond to window zooming and resizing

You need to follow the instructions in each step of this recipe to draw QuickDraw GX shapes into windows with a size box.

Functions Used in This Recipe

QuickDraw GX functions used in this recipe:
GXNewWindowViewPort"QuickDraw GX and the
Macintosh Environment"
QuickDraw GX Environment and Utilities
GXGetViewPortViewGroup"View-Related Objects"
QuickDraw GX Objects
GXNewViewPort"View-Related Objects"
QuickDraw GX Objects
GXSetViewPortParent"View-Related Objects"
QuickDraw GX Objects
GXConvertQDPoint"QuickDraw GX and the
Macintosh Environment"
QuickDraw GX Environment and Utilities
GXNewRectangle"Geometric Shapes"
QuickDraw GX Graphics
GXDifferenceShape"Geometric Operations"
QuickDraw GX Graphics
GXSetViewPortClip"View-Related Objects"
QuickDraw GX Objects
GXSetShapeViewPorts"Transform Objects"
QuickDraw GX Objects
GXDisposeShape"Shape Objects"
QuickDraw GX Objects

Standard Macintosh functions used in this recipe:
NewWindow"Window Manager"
Macintosh Toolbox Essentials
DrawGrowIcon"Window Manager"
Macintosh Toolbox Essentials

This recipe also uses a function from a QuickDraw GX library:
SetDefaultViewPortgraphics library

This recipe gives a brief description of these functions; you can find complete reference information for these functions in the Inside Macintosh suite of books.

Recipe Step Descriptions

In this section each step is described individually.

  1. Create a Macintosh window with a size box and a zoom box

    Before you can provide window resizing and zooming, you need to create a window with a size box and a zoom box. You can specify the zoomDocProc constant to the standard Macintosh function NewWindow to create a window with a zoom box.

    gWindow = NewWindow(nil, &windowRect, "\pWindow Title",
    true, zoomDocProc, (WindowPtr) -1,
    true, 0L);

    To draw a size box in this window, you use the standard Macintosh function DrawGrowIcon:

    DrawGrowIcon(gWindow);

    The size box appears in the lower-right corner of the content region of
    the window.

  2. Create a parent view port and attach it to the window

    Before you can draw QuickDraw GX shapes into the content region of the window, you must create a view port and attach it to the window, as you did in the previous recipe:

    gxViewPort gParentViewPort;

    gParentViewPort = GXNewWindowViewPort(gWindow);

    As before, QuickDraw GX manages this view port for you. That is, QuickDraw GX updates the value of this view port's clip and mapping properties to reflect the current size and position of associated window.

    Unfortunately, QuickDraw GX does not consider the area covered by the size box when calculating the clip property of the view port. As a result, if you draw shapes directly into this view port, you could possibly draw over the size box.

    To solve this problem, in the next step you create a simple view port hierarchy in which the window view port is the parent view port and the view port you draw into is the child view port, whose clip you can alter.

  3. Create a child view port

    To create a view port that is a child of the window view port, you must first determine the view group of the window view port.

    Remember that a view group describes an entire viewing coordinate system. As an example, all of your window view ports belong to the onscreen coordinate system.

    You can determine which view group a view port belongs to by using the GXGetViewPortViewGroup function:

    gxViewGroup onscreenViewGroup;

    onscreenViewGroup = GXGetViewPortViewGroup(parentViewPort);

    Since the parent view port belongs to the onscreen drawing environment, this function call finds the onscreen view group.

    To create another view port object in the same view group, you would use the GXNewViewPort function, which takes the view group as a parameter.

    gxViewPort gContentViewPort;

    gContentViewPort = GXNewViewPort(onscreenViewGroup);

    After this function call, the gContentViewPort variable references a new view port object in the same view group as the window view port. At this point, however, the two view ports are not connected, other than belonging to the onscreen view group. By specifying the clip and mapping of this new view port incorrectly, you could end up drawing QuickDraw GX shapes anywhere on the screen!

    You connect the new view port to the window view port by using the GXSetViewPortParent function:

    GXSetViewPortParent(gContentViewPort, parentViewPort);

    After this function call, the new view port is a child of the parent view port. Any drawing you do to the child view port is not only clipped by the child view port's clip, but also by the parent view port's clip. Now, if you draw a shape into the child view port, you may draw over the size box, but at least you won't draw outside the window!

  4. Set the clip of the child view port

    To make sure that you don't draw over the window's size box, you
    want to specify additional clipping for the child view port. The MySetContentViewPortClip function shows how you can set the clip property of the child view port so that you can't draw over the size box.

    void MySetContentViewPortClip(WindowPtr theWindow, 
    gxViewPort theChildViewPort)
    {
    gxRectangle parentBounds, sizeBoxBounds;
    gxShape contentClip, sizeBoxClip;

        contentClip = MyGetWindowBoundsShape(gCurrent->window);

        GXGetRectangle(contentClip, &parentBounds);

        sizeBoxBounds.bottom = parentBounds.bottom;
    sizeBoxBounds.right = parentBounds.right;
    sizeBoxBounds.top = sizeBoxBounds.bottom
    - ff(kScrollBarWidth);
    resizeBoxBounds.left = sizeBoxBounds.right
    - ff(kScrollBarWidth);


    sizeBoxClip = GXNewRectangle(&sizeBoxBounds);

        GXDifferenceShape(contentClip, sizeBoxClip);
    GXSetViewPortClip(theChildViewPort, contentClip);

        GXDisposeShape(contentClip);
    GXDisposeShape(sizeBoxClip);
    }

    This function calls the MyGetWindowBoundsShape sample function (defined later in this step) to find the bounding rectangle of the window in QuickDraw GX coordinate, translates those into local coordinates (fixed-
    point coordinates relative to the origin of the window view port), and encapsulates the bounding rectangle into a rectangle shape. The function then finds the bounding rectangle of the size box.

    The function then encapsulates the bounding rectangle of the size box into QuickDraw GX rectangle shapes, and uses the GXDifferenceShape function to find the shape that describes the area of the content region of the window that is not covered by the size box.

    The function finally sets the clip of the child view port to be this area. Subsequently, when you draw shapes into the child view port, they'll be clipped so that they don't draw over the size box.

    To set the clip of the child view port you created in the previous step, you make this function call:

    MySetContentViewPortClip(gWindow, gContentViewPort);

    The MyGetWindowBoundsShape function is defined as follows:

    gxShape MyGetWindowBoundsShape(WindowPtr theWindow)
    {
    Rect theQDRect;
    Point QDtopLeft;
    Point QDbotRight;
    gxPoint GXtopLeft;
    gxPoint GXbotRight;
    gxRectangle theGXRect;

        theRect = theWindow->portRect;
    QDtopLeft.h = theRect.left;
    QDtopLeft.v = theRect.top;
    QDtopLeft.h = theRect.right;
    QDtopLeft.v = theRect.bottom;

        GXConvertQDPoint(&QDtopLeft, 0, &GXtopLeft);
    GXConvertQDPoint(&QDbotRight, 0, &GXbotRight);

        theGXRect.top    = GXtopLeft.y;
    theGXRect.left = GXtopLeft.x;
    theGXRect.bottom = GXbotRight.y;
    theGXRect.right = GXbotRight.x;

        return(GXNewRectangle(&theGXRect));
    }
  5. Set the child view port to be the default view port

    As in the previous recipe, you can specify each shape that you want to draw into the child view port using the GXSetShapeViewPorts function:

    GXSetShapeViewPorts(eachShape, 1, &contentViewPort);

    Alternatively, you can make the child view port be the default view port:

    SetDefaultViewPort(contentViewPort);

    After this function call, shapes you create reference the child view port, which in turn references the parent view port. Therefore, when you draw them, QuickDraw GX renders them into your window, but clips them so that they don't draw over the size box.

  6. Respond to window zooming and resizing

    When the user moves or resizes the window, QuickDraw GX automatically updates the clip and mapping properties of the parent window for you, but it does not update those properties for the child view port.

    Fortunately, the origin of the child view port is relative to the origin of its parent, so you don't need to worry about updating the child's mapping. However, you do need to update the clip property of the child view port to reflect the new content region of the window. To do this, you simply call the MySetContentViewPortClip function defined in Step 4:

    MySetContentViewPortClip(gWindow, gContentViewPort);

    This function updates the clip property of the child view port to reflect the new window size.

Related Recipes

For other information related to using QuickDraw GX and Macintosh windows, see these recipes:

The recipes in the previous chapter, "Using the QuickDraw GX Environment," show you how to initialize QuickDraw GX and set up the QuickDraw GX debugging facilities. You should read the recipes in that chapter before using any recipes in this chapter.

The recipes in Chapter 6, "Handling Graphics," and in Chapter 7, "Handling Typography," show you how to create and manipulate images to draw into
a window.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996




Navigation graphic, see text links

Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help